#ifndef COMMON_H_
#define COMMON_H_

#include "sstream"
#include <pthread.h>
#include <sys/time.h>

namespace utility {

std::string itoa(uint32_t n);

uint32_t atoi(const std::string& str);

typedef void*(THREADFUNC) (void *arg);

int64_t startThread(THREADFUNC* func, void* arg);

int waitThread(pthread_t thread_id); 

int thread_cond_timewait(pthread_cond_t* cond, pthread_mutex_t* mutex, uint64_t sec);

//sleep time nanoseconds
void sleepnano(uint64_t time);
    
uint64_t nowMicros();

timespec getnow();

//milliseconds
int64_t gapBetween(const timespec& t1, const timespec& t2);

class PerformanceMeasure {

private:
    uint64_t m_start;
    uint64_t m_end;
    uint64_t m_num;
    double m_sum;
    std::string m_name;

public:
    PerformanceMeasure(const std::string& name);
    ~PerformanceMeasure();

    void start(); 
    void end();
    double avg();
    uint64_t getNum();
    uint64_t getCur();
};


//a simple class to manage array allocated by new[]
template<typename T>
class auto_array_ptr {

public:
    auto_array_ptr(): m_buf(NULL) {}
    auto_array_ptr( T* t ): m_buf( t ) {}
    ~auto_array_ptr() { delete[] m_buf; }
    T* get()  { return m_buf; }
    T* operator->()  { return m_buf; }
    void reset(T* t) {
     
        if(m_buf) delete[] m_buf;
        m_buf = t;
    }

    void release() {
        m_buf = NULL;
    }

private:
    T* m_buf;

    //no copy and assignemnt  
    auto_array_ptr(const auto_array_ptr& );
    void operator=(const auto_array_ptr& );    

};

//reference counting class
template<class T>
class Ref_counting {
private:
    T m_object;
    uint32_t m_count;

public:
    Ref_counting(T& t) 
    : m_object(t), m_count(0) {
    }

    T& get() { return m_object; }

    uint32_t count() { return m_count; }

    void incRef() { __sync_fetch_and_add(&m_count, 1); }
    void decRef() { __sync_fetch_and_add(&m_count, -1);}
};

}



#endif
